#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
邮件通知模块
提供邮件发送功能，支持HTML和纯文本格式
"""

import smtplib
import logging
from datetime import datetime
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from typing import Dict, Any, List, Optional
from .utils import validate_email_config

logger = logging.getLogger(__name__)

class EmailNotifier:
    """邮件通知器"""
    
    def __init__(self, config: Dict[str, Any]):
        """
        初始化邮件通知器
        
        Args:
            config: 邮件配置字典
        """
        self.config = config
        self.is_valid = False
        
        # 验证配置
        is_valid, error_msg = validate_email_config(config)
        if not is_valid:
            logger.error(f"邮件配置无效: {error_msg}")
            raise ValueError(f"邮件配置无效: {error_msg}")
        
        self.is_valid = True
        logger.info("邮件通知器初始化成功")
    
    def send_email(self, subject: str, body: str, recipients: Optional[List[str]] = None,
                   html_body: Optional[str] = None, attachments: Optional[List[str]] = None) -> bool:
        """
        发送邮件
        
        Args:
            subject: 邮件主题
            body: 邮件正文（纯文本）
            recipients: 收件人列表，为空时使用配置中的默认收件人
            html_body: HTML格式邮件正文（可选）
            attachments: 附件文件路径列表（可选）
        
        Returns:
            是否发送成功
        """
        if not self.is_valid:
            logger.error("邮件配置无效，无法发送邮件")
            return False
        
        try:
            # 使用默认收件人（如果未指定）
            if recipients is None:
                recipients = self.config.get('recipients', [])
            
            if not recipients:
                logger.error("未指定收件人")
                return False
            
            # 创建邮件对象
            if html_body or attachments:
                msg = MIMEMultipart('mixed')
                
                # 创建邮件内容部分
                content_part = MIMEMultipart('alternative')
                
                # 添加纯文本内容
                text_part = MIMEText(body, 'plain', 'utf-8')
                content_part.attach(text_part)
                
                # 添加HTML内容（如果提供）
                if html_body:
                    html_part = MIMEText(html_body, 'html', 'utf-8')
                    content_part.attach(html_part)
                
                msg.attach(content_part)
                
                # 添加附件（如果提供）
                if attachments:
                    for attachment_path in attachments:
                        if self._add_attachment(msg, attachment_path):
                            logger.info(f"已添加附件: {attachment_path}")
                        else:
                            logger.warning(f"添加附件失败: {attachment_path}")
            else:
                # 简单的纯文本邮件
                msg = MIMEText(body, 'plain', 'utf-8')
            
            # 设置邮件头
            msg['From'] = self.config['sender']
            msg['To'] = ', '.join(recipients)
            msg['Subject'] = Header(subject, 'utf-8')
            msg['Date'] = datetime.now().strftime('%a, %d %b %Y %H:%M:%S %z')
            
            # 连接SMTP服务器并发送邮件
            with smtplib.SMTP(self.config['server'], self.config['port']) as server:
                # 启用调试（可选）
                if logger.isEnabledFor(logging.DEBUG):
                    server.set_debuglevel(1)
                
                # 启用TLS加密
                if self.config.get('use_tls', True):
                    server.starttls()
                
                # 登录（如果需要）
                if self.config.get('username') and self.config.get('password'):
                    server.login(self.config['username'], self.config['password'])
                
                # 发送邮件
                server.send_message(msg)
            
            logger.info(f"邮件发送成功: {subject} -> {', '.join(recipients)}")
            return True
        
        except Exception as e:
            logger.error(f"发送邮件失败: {e}")
            return False
    
    def _add_attachment(self, msg: MIMEMultipart, file_path: str) -> bool:
        """
        添加附件到邮件
        
        Args:
            msg: 邮件对象
            file_path: 附件文件路径
        
        Returns:
            是否添加成功
        """
        try:
            import os
            from email.mime.base import MIMEBase
            from email import encoders
            
            if not os.path.exists(file_path):
                logger.error(f"附件文件不存在: {file_path}")
                return False
            
            with open(file_path, 'rb') as f:
                attachment = MIMEBase('application', 'octet-stream')
                attachment.set_payload(f.read())
            
            encoders.encode_base64(attachment)
            attachment.add_header(
                'Content-Disposition',
                f'attachment; filename= {os.path.basename(file_path)}'
            )
            
            msg.attach(attachment)
            return True
        
        except Exception as e:
            logger.error(f"添加附件失败 {file_path}: {e}")
            return False
    
    def send_alert(self, alert_type: str, message: str, details: Optional[Dict[str, Any]] = None) -> bool:
        """
        发送告警邮件
        
        Args:
            alert_type: 告警类型
            message: 告警消息
            details: 详细信息
        
        Returns:
            是否发送成功
        """
        subject = f"🚨 系统告警 - {alert_type}"
        
        # 构建邮件正文
        body_lines = [
            f"告警类型: {alert_type}",
            f"告警时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            f"告警消息: {message}",
            ""
        ]
        
        if details:
            body_lines.append("详细信息:")
            for key, value in details.items():
                body_lines.append(f"  {key}: {value}")
        
        body_lines.extend([
            "",
            "请及时处理相关问题。",
            "",
            "此邮件由通用服务器监控系统自动发送。"
        ])
        
        body = "\n".join(body_lines)
        
        # 构建HTML邮件正文
        html_body = self._create_alert_html(alert_type, message, details)
        
        return self.send_email(subject, body, html_body=html_body)
    
    def send_report(self, report_type: str, report_data: Dict[str, Any]) -> bool:
        """
        发送监控报告邮件
        
        Args:
            report_type: 报告类型（daily, weekly, monthly）
            report_data: 报告数据
        
        Returns:
            是否发送成功
        """
        type_names = {
            'daily': '日报',
            'weekly': '周报',
            'monthly': '月报'
        }
        
        report_name = type_names.get(report_type, report_type)
        subject = f"📊 系统监控{report_name} - {datetime.now().strftime('%Y-%m-%d')}"
        
        # 构建邮件正文
        body = self._create_report_text(report_type, report_data)
        
        # 构建HTML邮件正文
        html_body = self._create_report_html(report_type, report_data)
        
        return self.send_email(subject, body, html_body=html_body)
    
    def _create_alert_html(self, alert_type: str, message: str, 
                          details: Optional[Dict[str, Any]] = None) -> str:
        """创建告警邮件的HTML内容"""
        html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <style>
                body {{ font-family: Arial, sans-serif; margin: 20px; }}
                .alert {{ background-color: #f8d7da; border: 1px solid #f5c6cb; 
                         border-radius: 5px; padding: 15px; margin: 10px 0; }}
                .alert-header {{ font-size: 18px; font-weight: bold; color: #721c24; }}
                .alert-time {{ color: #6c757d; font-size: 14px; }}
                .details {{ background-color: #f8f9fa; border-radius: 5px; 
                           padding: 10px; margin: 10px 0; }}
                .details-title {{ font-weight: bold; margin-bottom: 5px; }}
                .footer {{ margin-top: 20px; padding-top: 10px; 
                          border-top: 1px solid #dee2e6; color: #6c757d; font-size: 12px; }}
            </style>
        </head>
        <body>
            <div class="alert">
                <div class="alert-header">🚨 系统告警 - {alert_type}</div>
                <div class="alert-time">告警时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</div>
                <p><strong>告警消息:</strong> {message}</p>
        """
        
        if details:
            html += """
                <div class="details">
                    <div class="details-title">详细信息:</div>
            """
            for key, value in details.items():
                html += f"<div><strong>{key}:</strong> {value}</div>"
            html += "</div>"
        
        html += """
                <p>请及时处理相关问题。</p>
            </div>
            <div class="footer">
                此邮件由通用服务器监控系统自动发送。
            </div>
        </body>
        </html>
        """
        
        return html
    
    def _create_report_text(self, report_type: str, report_data: Dict[str, Any]) -> str:
        """创建报告邮件的纯文本内容"""
        type_names = {
            'daily': '日报',
            'weekly': '周报',
            'monthly': '月报'
        }
        
        report_name = type_names.get(report_type, report_type)
        
        lines = [
            f"系统监控{report_name}",
            "=" * 50,
            f"报告时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            ""
        ]
        
        # 系统概览
        if 'system_overview' in report_data:
            overview = report_data['system_overview']
            lines.extend([
                "系统概览:",
                f"  运行时间: {overview.get('uptime', 'N/A')}",
                f"  CPU使用率: {overview.get('cpu_usage', 'N/A')}%",
                f"  内存使用率: {overview.get('memory_usage', 'N/A')}%",
                f"  磁盘使用率: {overview.get('disk_usage', 'N/A')}%",
                ""
            ])
        
        # 告警统计
        if 'alerts' in report_data:
            alerts = report_data['alerts']
            lines.extend([
                "告警统计:",
                f"  总告警数: {alerts.get('total', 0)}",
                f"  严重告警: {alerts.get('critical', 0)}",
                f"  警告告警: {alerts.get('warning', 0)}",
                ""
            ])
        
        # 性能趋势
        if 'performance' in report_data:
            perf = report_data['performance']
            lines.extend([
                "性能趋势:",
                f"  平均CPU使用率: {perf.get('avg_cpu', 'N/A')}%",
                f"  平均内存使用率: {perf.get('avg_memory', 'N/A')}%",
                f"  峰值CPU使用率: {perf.get('max_cpu', 'N/A')}%",
                f"  峰值内存使用率: {perf.get('max_memory', 'N/A')}%",
                ""
            ])
        
        lines.extend([
            "此邮件由通用服务器监控系统自动发送。"
        ])
        
        return "\n".join(lines)
    
    def _create_report_html(self, report_type: str, report_data: Dict[str, Any]) -> str:
        """创建报告邮件的HTML内容"""
        type_names = {
            'daily': '日报',
            'weekly': '周报',
            'monthly': '月报'
        }
        
        report_name = type_names.get(report_type, report_type)
        
        html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <style>
                body {{ font-family: Arial, sans-serif; margin: 20px; }}
                .header {{ background-color: #007bff; color: white; padding: 15px; 
                          border-radius: 5px; text-align: center; }}
                .section {{ margin: 20px 0; padding: 15px; border: 1px solid #dee2e6; 
                           border-radius: 5px; }}
                .section-title {{ font-size: 16px; font-weight: bold; 
                                 margin-bottom: 10px; color: #495057; }}
                .metric {{ display: flex; justify-content: space-between; 
                          padding: 5px 0; border-bottom: 1px solid #f8f9fa; }}
                .metric:last-child {{ border-bottom: none; }}
                .metric-name {{ font-weight: bold; }}
                .metric-value {{ color: #007bff; }}
                .footer {{ margin-top: 20px; padding-top: 10px; 
                          border-top: 1px solid #dee2e6; color: #6c757d; font-size: 12px; }}
            </style>
        </head>
        <body>
            <div class="header">
                <h2>📊 系统监控{report_name}</h2>
                <p>报告时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
            </div>
        """
        
        # 系统概览
        if 'system_overview' in report_data:
            overview = report_data['system_overview']
            html += """
            <div class="section">
                <div class="section-title">系统概览</div>
            """
            for key, value in overview.items():
                display_names = {
                    'uptime': '运行时间',
                    'cpu_usage': 'CPU使用率',
                    'memory_usage': '内存使用率',
                    'disk_usage': '磁盘使用率'
                }
                display_name = display_names.get(key, key)
                display_value = f"{value}%" if key.endswith('_usage') else value
                html += f"""
                <div class="metric">
                    <span class="metric-name">{display_name}</span>
                    <span class="metric-value">{display_value}</span>
                </div>
                """
            html += "</div>"
        
        # 告警统计
        if 'alerts' in report_data:
            alerts = report_data['alerts']
            html += """
            <div class="section">
                <div class="section-title">告警统计</div>
            """
            alert_names = {
                'total': '总告警数',
                'critical': '严重告警',
                'warning': '警告告警'
            }
            for key, value in alerts.items():
                display_name = alert_names.get(key, key)
                html += f"""
                <div class="metric">
                    <span class="metric-name">{display_name}</span>
                    <span class="metric-value">{value}</span>
                </div>
                """
            html += "</div>"
        
        # 性能趋势
        if 'performance' in report_data:
            perf = report_data['performance']
            html += """
            <div class="section">
                <div class="section-title">性能趋势</div>
            """
            perf_names = {
                'avg_cpu': '平均CPU使用率',
                'avg_memory': '平均内存使用率',
                'max_cpu': '峰值CPU使用率',
                'max_memory': '峰值内存使用率'
            }
            for key, value in perf.items():
                display_name = perf_names.get(key, key)
                display_value = f"{value}%" if value != 'N/A' else value
                html += f"""
                <div class="metric">
                    <span class="metric-name">{display_name}</span>
                    <span class="metric-value">{display_value}</span>
                </div>
                """
            html += "</div>"
        
        html += """
            <div class="footer">
                此邮件由通用服务器监控系统自动发送。
            </div>
        </body>
        </html>
        """
        
        return html
    
    def test_connection(self) -> bool:
        """
        测试邮件服务器连接
        
        Returns:
            是否连接成功
        """
        try:
            with smtplib.SMTP(self.config['server'], self.config['port']) as server:
                if self.config.get('use_tls', True):
                    server.starttls()
                
                if self.config.get('username') and self.config.get('password'):
                    server.login(self.config['username'], self.config['password'])
            
            logger.info("邮件服务器连接测试成功")
            return True
        
        except Exception as e:
            logger.error(f"邮件服务器连接测试失败: {e}")
            return False
    
    def send_test_email(self, recipient: Optional[str] = None) -> bool:
        """
        发送测试邮件
        
        Args:
            recipient: 测试邮件收件人，为空时使用配置中的第一个收件人
        
        Returns:
            是否发送成功
        """
        if recipient:
            recipients = [recipient]
        else:
            recipients = self.config.get('recipients', [])[:1]  # 只发送给第一个收件人
        
        if not recipients:
            logger.error("未指定测试邮件收件人")
            return False
        
        subject = "📧 通用服务器监控系统 - 测试邮件"
        body = f"""
这是一封测试邮件，用于验证邮件通知功能是否正常工作。

发送时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
收件人: {recipients[0]}

如果您收到这封邮件，说明邮件通知功能配置正确。

此邮件由通用服务器监控系统自动发送。
        """
        
        html_body = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <style>
                body {{ font-family: Arial, sans-serif; margin: 20px; }}
                .test-email {{ background-color: #d4edda; border: 1px solid #c3e6cb; 
                             border-radius: 5px; padding: 15px; }}
                .test-header {{ font-size: 18px; font-weight: bold; color: #155724; }}
            </style>
        </head>
        <body>
            <div class="test-email">
                <div class="test-header">📧 通用服务器监控系统 - 测试邮件</div>
                <p>这是一封测试邮件，用于验证邮件通知功能是否正常工作。</p>
                <p><strong>发送时间:</strong> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
                <p><strong>收件人:</strong> {recipients[0]}</p>
                <p>如果您收到这封邮件，说明邮件通知功能配置正确。</p>
                <p><em>此邮件由通用服务器监控系统自动发送。</em></p>
            </div>
        </body>
        </html>
        """
        
        return self.send_email(subject, body, recipients, html_body)